package com.afterglow.lcsrpc.utils;

import cn.hutool.core.util.StrUtil;
import cn.hutool.setting.dialect.Props;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;

import java.io.InputStream;
import java.util.Map;

/**
 * Description:配置工具类
 * Date: 2024/12/08
 * author: lcs
 */
public class ConfigUtils {

    private static Props props;
    private static Map<String, Object> yamlConfig;

    /**
     * 加载配置对象
     * @param tClass
     * @param prefix
     * @return
     * @param <T>
     */
    public static <T> T loadConfig(Class<T> tClass, String prefix){
        return loadConfig(tClass, prefix, "");
    }

    public static <T> T loadConfig(Class<T> tClass, String prefix, String environment){
        String configFile = getConfigFileName(environment);

        if (configFile.endsWith(".properties")) {
            // 动态加载 .properties 文件
            props = new Props(configFile);

            props.autoLoad(true);

            return props.toBean(tClass, prefix);

        } else if (configFile.endsWith(".yml") || configFile.endsWith(".yaml")) {
            // 加载 .yml 或 .yaml 文件
            loadYamlConfig(configFile);

            // 监听 YAML 文件变更（需自定义监听逻辑）
            startYamlWatcher(configFile);

            // 返回初始加载配置
            Map<String, Object> subConfig = (Map<String, Object>) yamlConfig.get(prefix);
            return mapToBean(subConfig, tClass);

        } else {
            throw new IllegalArgumentException("Unsupported configuration file format: " + configFile);
        }
    }

    private static void loadYamlConfig(String configFile) {
        try (InputStream inputStream = ConfigUtils.class.getClassLoader().getResourceAsStream(configFile)) {
            if (inputStream == null) {
                throw new IllegalArgumentException("Configuration file not found: " + configFile);
            }
            ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory());
            yamlConfig = objectMapper.readValue(inputStream, Map.class);
        } catch (Exception e) {
            throw new RuntimeException("Failed to load YAML configuration file: " + configFile, e);
        }
    }

    private static void startYamlWatcher(String configFile) {
        // 启动后台线程监控 YAML 文件的变更
        new Thread(() -> {
            while (true) {
                try {
                    Thread.sleep(5000); // 每 5 秒检测一次变更
                    // 检测文件是否修改并重新加载配置
                    reloadYamlIfChanged(configFile);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    private static void reloadYamlIfChanged(String configFile) {
        // 检测文件是否修改并重新加载
        Map<String, Object> newConfig = null;
        try (InputStream inputStream = ConfigUtils.class.getClassLoader().getResourceAsStream(configFile)) {
            if (inputStream != null) {
                ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory());
                newConfig = objectMapper.readValue(inputStream, Map.class);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (newConfig != null && !newConfig.equals(yamlConfig)) {
            yamlConfig = newConfig;
            System.out.println("YAML 配置文件已更新: " + configFile);
        }
    }

    private static <T> T mapToBean(Map<String, Object> map, Class<T> tClass) {
        if (map == null) {
            throw new IllegalArgumentException("Configuration for the specified prefix not found.");
        }
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.convertValue(map, tClass);
    }

    private static String getConfigFileName(String environment) {
        StringBuilder configFileBuild = new StringBuilder("application");
        if (StrUtil.isNotBlank(environment)) {
            configFileBuild.append("-").append(environment);
        }
        // 根据实际需求扩展文件格式（按顺序优先加载 properties -> yml）
        if (ConfigUtils.class.getClassLoader().getResource(configFileBuild + ".properties") != null) {
            return configFileBuild + ".properties";
        } else if (ConfigUtils.class.getClassLoader().getResource(configFileBuild + ".yml") != null) {
            return configFileBuild + ".yml";
        } else if (ConfigUtils.class.getClassLoader().getResource(configFileBuild + ".yaml") != null) {
            return configFileBuild + ".yaml";
        } else {
            throw new IllegalArgumentException("No configuration file found for environment: " + environment);
        }
    }
}
